home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 49 / Amiga Format CD49 (2000-01-17)(Future Publishing)(GB)(Track 1 of 3)[!][issue 2000-02].iso / -serious- / misc / pdflib / test / pdftest.c < prev    next >
C/C++ Source or Header  |  1999-12-06  |  25KB  |  988 lines

  1. /*---------------------------------------------------------------------------*
  2.  |        PDFlib - A library for dynamically generating PDF files            |
  3.  +---------------------------------------------------------------------------+
  4.  |        Copyright (c) 1997-1999 Thomas Merz. All rights reserved.          |
  5.  +---------------------------------------------------------------------------+
  6.  |    This software is not in the public domain.  It is subject to the       |
  7.  |    "Aladdin Free Public License".  See the file license.txt for details.  |
  8.  |    This license grants you the right to use and redistribute PDFlib       |
  9.  |    under certain conditions. Among other things, the license requires     |
  10.  |    that the copyright notice and this notice be preserved on all copies.  |
  11.  |    This requirement extends to ports to other programming languages.      |
  12.  |                                                                           |
  13.  |    In short, you are allowed to develop and use PDFlib-based software     |
  14.  |    as long as you don't sell it. Commercial use of PDFlib requires a      |
  15.  |    commercial license which can be obtained from the author of PDFlib.    |
  16.  |    Contact information can be found in the accompanying PDFlib manual.    |
  17.  |    PDFlib is distributed with no warranty of any kind. Commercial users,  |
  18.  |    however, will receive warranty and support statements in writing.      |
  19.  *---------------------------------------------------------------------------*/
  20.  
  21. /* pdftest.c
  22.  *
  23.  * Test bed and sample application for PDFlib
  24.  */
  25.  
  26. #ifdef WIN32
  27.     /* Visual C++ seems to need this in order to fetch the thread functions */
  28.     #ifndef _MT
  29.     #define _MT
  30.     #endif
  31.  
  32.     #include <windows.h>
  33.     #include <process.h>
  34. #endif    /* WIN32 */
  35.  
  36. #include <stdio.h>
  37. #include <string.h>
  38. #include <stdlib.h>
  39. #include <math.h>
  40.  
  41. #include "pdflib.h"
  42.  
  43. #if __POWERPC__ || __CFM68K__ || __MC68K__
  44. #define MAC
  45. #endif
  46.  
  47. /* Don't clutter output from many threads with messages */
  48. #ifdef WIN32
  49. #define MESSAGE(m)        /* */
  50. #define PDF_ENDTHREAD(val)    _endthreadex(val);
  51. #else
  52. #define MESSAGE(m)        fprintf(stderr, m)
  53. #define PDF_ENDTHREAD(val)    /* */
  54. #endif
  55.  
  56. /* ------------------------------------------------------------- */
  57. static void
  58. bookmarks(PDF *p)
  59. {
  60. #define UNICODEINFO    "\xFE\xFF\0001\000.\000A\0\0"
  61. #define LEFT 50
  62. #define FONTSIZE 24
  63. #define LEAD ((int) (FONTSIZE * 1.5))
  64.  
  65.     unsigned char buf[64], tmp[64];
  66.     int c, i, pos;
  67.     float y=700;
  68.     int level1, level2=0, level3=0, font;
  69.  
  70.     MESSAGE("Bookmark test...");
  71.  
  72.     font = PDF_findfont(p, "Helvetica", "default", 0);
  73.     if (font == -1) {
  74.     fprintf(stderr, "\nFont %s not found!\n", "Helvetica");
  75.     return;
  76.     }
  77.  
  78.     PDF_begin_page(p, a4_width, a4_height);
  79.  
  80.     PDF_setfont(p, font, FONTSIZE);
  81.  
  82.     PDF_show_xy(p, "The bookmarks for this page contain all", LEFT, y-=LEAD);
  83.     PDF_show_xy(p, "Unicode characters.", LEFT, y-=LEAD);
  84.     PDF_show_xy(p, "Depending on the available fonts,", LEFT, y-=LEAD);
  85.     PDF_show_xy(p, "only a certain subset will be visible on", LEFT, y-=LEAD);
  86.     PDF_show_xy(p, "your system.", LEFT, y-=LEAD);
  87.     
  88.     /* private Unicode info entry */
  89.     PDF_set_info(p, "Revision", UNICODEINFO);
  90.  
  91.     /* Generate Unicode bookmarks */
  92.     level1 = PDF_add_bookmark(p, "Unicode bookmarks", 0, 0);
  93.  
  94.     for (c = 0; c < 65535; c += 16) {
  95.     if (c % 4096 == 0) {
  96.         sprintf((char *) tmp, "U+%04X", c);
  97.         level2 = PDF_add_bookmark(p, (char *) tmp, level1, 0);
  98.     }
  99.     if (c % 256 == 0) {
  100.         sprintf((char *) tmp, "U+%04X", c);
  101.         level3 = PDF_add_bookmark(p, (char *) tmp, level2, 0);
  102.     }
  103.     /* now comes the actual Unicode string with the BOM */
  104.     sprintf((char *) tmp, "0x%04X: ", c);
  105.  
  106.     /* write the Unicode byte order mark */
  107.     strcpy((char *) buf, "\376\377");
  108.  
  109.     for (pos = 0; tmp[pos/2]; /* */ ) {
  110.         buf[2+pos++] = 0;
  111.         buf[2+pos++] = tmp[pos/2];    /* construct Unicode string */
  112.     }
  113.  
  114.     pos += 2;     /* account for the BOM */
  115.     for (i = 0; i < 16; i++) {    /* continue filling buf with chars */
  116.         buf[pos++] = (unsigned char) ((((c+i)) & 0xFF00) >> 8);
  117.         buf[pos++] = (unsigned char) (((c+i)) & 0x00FF);
  118.     }
  119.  
  120.     /* signal end of string with two null bytes */
  121.     buf[pos++] = (unsigned char) 0;
  122.     buf[pos++] = (unsigned char) 0;
  123.  
  124.     (void) PDF_add_bookmark(p, (char *) buf, level3, 1);
  125.     }
  126.  
  127.     PDF_end_page(p);
  128.  
  129.     MESSAGE("done\n");
  130.  
  131. #undef FONTSIZE
  132. #undef LEFT
  133. #undef UNICODEINFO
  134. #undef LEAD
  135. }
  136.  
  137. /* ------------------------------------------------------------- */
  138. static void
  139. ccitt_image(PDF *p)
  140. {
  141.     int    image;
  142.     float    sx, sy;
  143.  
  144. #define CCITTFILE    "tm.g3"
  145. #define WIDTH        591
  146. #define HEIGHT        236
  147.  
  148. /* Scale to non-standard fax resolutions */
  149. #define FAX_DPI_X    72
  150. #define FAX_DPI_Y    72
  151.  
  152.     sx = (float) (72.0 / FAX_DPI_X);
  153.     sy = (float) (72.0 / FAX_DPI_Y);
  154.  
  155.     MESSAGE("CCITT test...");
  156.  
  157.     if ((image = PDF_open_CCITT(p, CCITTFILE, WIDTH, HEIGHT, 0, 0, 0)) == -1) {
  158.     fprintf(stderr, "Error: Couldn't open CCITT image %s.\n", CCITTFILE);
  159.     return;
  160.     }
  161.  
  162.     PDF_begin_page(p, (float) PDF_get_image_width(p, image) * sx,
  163.             (float) PDF_get_image_height(p, image) * sy);
  164.  
  165.     (void) PDF_add_bookmark(p, "CCITT image", 0, 1);
  166.  
  167.     PDF_scale(p, sx, sy);
  168.     PDF_place_image(p, image, (float) 0.0, (float) 0.0, (float) 1.0);
  169.  
  170.     PDF_end_page(p);
  171.  
  172.     MESSAGE("done\n");
  173.  
  174. #undef CCITTFILE
  175. }
  176.  
  177. /* ------------------------------------------------------------- */
  178. static void
  179. gif_image(PDF *p)
  180. {
  181.     int    image;
  182.  
  183. #define GIFFILE        "pdflib.gif"
  184.  
  185.     MESSAGE("GIF test...");
  186.  
  187.     if ((image = PDF_open_GIF(p, GIFFILE)) == -1) {
  188.     fprintf(stderr, "Error: Couldn't analyze GIF image %s.\n", GIFFILE);
  189.     return;
  190.     }
  191.  
  192.     PDF_begin_page(p, (float) PDF_get_image_width(p, image),
  193.                 (float) PDF_get_image_height(p, image));
  194.     (void) PDF_add_bookmark(p, "GIF image", 0, 1);
  195.  
  196.     PDF_place_image(p, image, (float) 0.0, (float) 0.0, (float) 1.0);
  197.  
  198.     PDF_end_page(p);
  199.  
  200.     MESSAGE("done\n");
  201.  
  202. #undef GIFFILE
  203. }
  204.  
  205. /* ------------------------------------------------------------- */
  206. #ifdef HAVE_LIBTIFF
  207. static void
  208. tiff_image(PDF *p)
  209. {
  210.     int    image;
  211.  
  212. #define TIFFFILE    "acroweb_j.tif"
  213.  
  214.     MESSAGE("TIFF test...");
  215.  
  216.     if ((image = PDF_open_TIFF(p, TIFFFILE)) == -1) {
  217.     fprintf(stderr, "Error: Couldn't analyze TIFF image %s.\n", TIFFFILE);
  218.     return;
  219.     }
  220.  
  221.     PDF_begin_page(p, PDF_get_image_width(p, image), PDF_get_image_height(p, image));
  222.     (void) PDF_add_bookmark(p, "TIFF image", 0, 1);
  223.  
  224.     PDF_place_image(p, image, 0.0, 0.0, 1.0);
  225.  
  226.     PDF_end_page(p);
  227.  
  228.     MESSAGE("done\n");
  229.  
  230. #undef TIFFFILE
  231. }
  232. #endif
  233.  
  234. /* ------------------------------------------------------------- */
  235. static void
  236. jpeg_image(PDF *p)
  237. {
  238.     int    image;
  239.     float    scale;
  240.  
  241. #define JPEGFILE    "nesrin.jpg"
  242.  
  243.     MESSAGE("JPEG test...");
  244.  
  245.     if ((image = PDF_open_JPEG(p, JPEGFILE)) == -1) {
  246.     fprintf(stderr, "Error: Couldn't analyze JPEG image %s.\n", JPEGFILE);
  247.     return;
  248.     }
  249.  
  250.     PDF_begin_page(p, a4_width, a4_height);
  251.     (void) PDF_add_bookmark(p, "JPEG image", 0, 1);
  252.  
  253.     /* ----------------- first image ------------------- */
  254.     /* fit image to page width */
  255.     scale = (float) a4_width/PDF_get_image_width(p, image);
  256.     PDF_place_image(p, image, (float) 0.0, 
  257.         a4_height - PDF_get_image_height(p, image) * scale, scale);
  258.  
  259.     /* ----------------- second image ------------------- */
  260.     scale = (float) 0.5;
  261.     PDF_save(p);
  262.     PDF_rotate(p, (float) 90.0);
  263.     PDF_place_image(p, image, (float) 0, (float) (-1 * a4_width), scale);
  264.     PDF_restore(p);
  265.  
  266.     /* ----------------- third image ------------------- */
  267.     scale = (float) 0.25;
  268.     PDF_save(p);
  269.     PDF_rotate(p, (float) 45.0);
  270.     PDF_place_image(p, image, (float) 200, (float) 0.0, scale);
  271.     PDF_restore(p);
  272.  
  273.     PDF_end_page(p);
  274.  
  275.     MESSAGE("done\n");
  276.  
  277. #undef JPEGFILE
  278. }
  279.  
  280. /* ------------------------------------------------------------- */
  281. static void
  282. character_table(PDF *p)
  283. {
  284.     char    text[50];
  285.     int        i, j, font;
  286.     float    x, y;
  287.  
  288. #define LEFT        50
  289. #define TOP        700
  290. #define FONTSIZE    16
  291. #define FONTNAME    "Times-Roman"
  292.  
  293. #ifdef MAC
  294.     #define ENCODING    "macroman"
  295. #else
  296.     #define ENCODING    "winansi"
  297. #endif
  298.  
  299.     MESSAGE("Character encoding test...");
  300.  
  301.     font = PDF_findfont(p, FONTNAME, ENCODING, 1);
  302.     if (font == -1) {
  303.     fprintf(stderr, "Font not found!\n");
  304.     return;
  305.     }
  306.  
  307.     PDF_begin_page(p, a4_width, a4_height);
  308.  
  309. #ifdef MAC
  310.     (void) PDF_add_bookmark(p, "MacOS Encoding", 0, 1);
  311.  
  312.     PDF_setfont(p, font, 2*FONTSIZE);
  313.     PDF_show_xy(p, "MacOS Encoding (no Symbol characters)",
  314.             LEFT, TOP+2*FONTSIZE);
  315. #else
  316.     (void) PDF_add_bookmark(p, "Windows Encoding", 0, 1);
  317.  
  318.     PDF_setfont(p, font, 2*FONTSIZE);
  319.     PDF_show_xy(p, "Windows Encoding", LEFT, TOP+2*FONTSIZE);
  320. #endif
  321.  
  322.     PDF_setfont(p, font, FONTSIZE);
  323.     text[1] = 0;
  324.  
  325.     y = TOP;
  326.     for (i = 2; i < 16; i++) {
  327.     y -=  2*FONTSIZE;
  328.     x = LEFT;
  329.     for (j = 0; j < 16; j++) {
  330.         text[0] = (char) (i*16 + j);
  331.         PDF_show_xy(p, text, x, y);
  332.         x += 2*FONTSIZE;
  333.     }
  334.     }
  335.  
  336.     PDF_end_page(p);
  337.  
  338.     MESSAGE("done\n");
  339.  
  340. #undef LEFT
  341. #undef TOP
  342. #undef FONTSIZE
  343. #undef FONTNAME
  344. }
  345.  
  346. /* ------------------------------------------------------------- */
  347. static void
  348. grid(PDF *p)
  349. {
  350. #define STEP        10
  351. #define FONTSIZE    ((float) 10.0)
  352. #define THICK        ((float) 1.0)
  353. #define THIN        ((float) 0.01)
  354.  
  355.     char buf[10];
  356.     float i;
  357.     float width = a4_width, height = a4_height;
  358.     int font;
  359.  
  360.     MESSAGE("Grid test...");
  361.  
  362.     PDF_begin_page(p, width, height);
  363.     (void) PDF_add_bookmark(p, "Grid", 0, 1);
  364.  
  365.     PDF_setlinewidth(p, THIN);
  366.     PDF_setdash(p, (float) 1.0, (float) 2.0);
  367.  
  368.     /* draw vertical lines */
  369.     for (i = 0; i < width; i += STEP) {
  370.     PDF_save(p);
  371.     if ((int) i % 100 == 0)
  372.         PDF_setlinewidth(p, THICK);
  373.     if ((int) i % 50 == 0)
  374.         PDF_setdash(p, (float) 0.0, (float) 0.0);
  375.     PDF_moveto(p, i, 0);
  376.     PDF_lineto(p, i, (float) height);
  377.     PDF_stroke(p);
  378.     PDF_restore(p);
  379.     }
  380.  
  381.     /* draw horizontal lines */
  382.     for (i = 0; i < height; i += STEP) {
  383.     PDF_save(p);
  384.     if ((int) i % 50 == 0)
  385.         PDF_setdash(p, (float) 0.0, (float) 0.0);
  386.     if ((int) i % 100 == 0)
  387.         PDF_setlinewidth(p, THICK);
  388.     PDF_moveto(p, 0, i);
  389.     PDF_lineto(p, (float) width, i);
  390.     PDF_stroke(p);
  391.     PDF_restore(p);
  392.     }
  393.  
  394. #define FONTNAME    "Helvetica-Bold"
  395. #define DELTA    ((float) 9)
  396. #define RADIUS    ((float) 12.0)
  397.  
  398.     font = PDF_findfont(p, FONTNAME, "default", 0);
  399.  
  400.     if (font == -1)
  401.     fprintf(stderr, "Font %s not found!\n", FONTNAME);
  402.  
  403.     PDF_setfont(p, font, FONTSIZE);
  404.  
  405.     /* print captions */
  406.     for (i = 100; i < width; i+= 100) {
  407.     PDF_save(p);
  408.     PDF_setgray_fill(p, (float) 1.0);
  409.     PDF_circle(p, i, (float) 20.0, RADIUS);
  410.     PDF_fill(p);
  411.     PDF_restore(p);
  412.     sprintf(buf, "%d", (int) i);
  413.     PDF_show_xy(p, buf, i - DELTA, (float) 20.0 - FONTSIZE/3);
  414.     }
  415.  
  416.     for (i = 100; i < height; i+= 100) {
  417.     PDF_save(p);
  418.     PDF_setgray_fill(p, (float) 1.0);
  419.     PDF_circle(p, (float) 40.0, i, RADIUS);
  420.     PDF_fill(p);
  421.     PDF_restore(p);
  422.     sprintf(buf, "%d", (int) i);
  423.     PDF_show_xy(p, buf, (float) 40.0 - DELTA, i - FONTSIZE/3);
  424.     }
  425.  
  426.     PDF_end_page(p);
  427.  
  428.     MESSAGE("done\n");
  429.  
  430. #undef STEP
  431. #undef FONTSIZE
  432. #undef DELTA
  433. #undef RADIUS
  434. #undef FONTNAME
  435. }
  436.  
  437.  
  438. /* ------------------------------------------------------------- */
  439. static void
  440. shaded_circle(PDF *p)
  441. {
  442.     int i, step = 1;
  443.     float gray = (float) 0.1, r;
  444.  
  445.     MESSAGE("Shaded circle test...");
  446.  
  447.     /* generate perceptual linear color blend */
  448.     r = (float) pow(1.0/gray, 1.0/255.0);
  449.  
  450.     PDF_begin_page(p, a4_width, a4_height);
  451.     (void) PDF_add_bookmark(p, "Shaded circle", 0, 1);
  452.  
  453.     for (i = 255; i >= 0; i--) {
  454.     PDF_setrgbcolor_fill(p, gray, gray, (float) 1.0);
  455.     PDF_circle(p, (float) 300.0, (float) 400.0, (float) i);
  456.     PDF_fill(p);
  457.     gray *= r;
  458.     }
  459.     PDF_end_page(p);
  460.  
  461.     MESSAGE("done\n");
  462. }
  463.  
  464.  
  465. /* ------------------------------------------------------------- */
  466. static void
  467. annotations(PDF *p)
  468. {
  469. #define FILENAME    "pdftest.c"
  470. #define MIMETYPE    "text/plain"
  471. #define NOTETEXT    "Hi! I'm a text annotation!"
  472.  
  473. /* Some greek and russian words for the unicode annotation test */
  474. #define GREEKTEXT    "\xFE\xFF\003\233\003\237\003\223\003\237\003\243\0\0"
  475. #define RUSSIANTEXT    "\xFE\xFF\004\037\004\036\004\024\004\040\004\043\004\023\004\020\0\0"
  476.  
  477.     MESSAGE("Annotation test...");
  478.  
  479.     PDF_begin_page(p, a4_width, a4_height);
  480.  
  481.     (void) PDF_add_bookmark(p, "Annotations", 0, 1);
  482.  
  483.     (void) PDF_attach_file(p, 100, 200, 150, 250, FILENAME,
  484.             "C source file", "Thomas Merz", MIMETYPE, "graph");
  485.  
  486.     PDF_set_border_style(p, "dashed", (float) 3.0);
  487.     PDF_set_border_color(p, (float) 0.0, (float) 0.0, (float) 1.0);
  488.     PDF_set_border_dash(p, (float) 5.0, (float) 1.0);
  489.  
  490.     PDF_add_note(p, 200, 400, 300, 450, NOTETEXT, "Thomas Merz", "comment", 0);
  491.  
  492.     PDF_set_border_style(p, "dashed", (float) 4.0);
  493.     PDF_set_border_color(p, (float) 1.0, (float) 0.0, (float) 0.0);
  494.     PDF_set_border_dash(p, (float) 1.0, (float) 4.0);
  495.  
  496.     PDF_add_note(p, 200, 600, 550, 750, GREEKTEXT, "Greek annotation",
  497.             "insert",1);
  498.  
  499.     PDF_add_note(p, 100, 500, 400, 650, RUSSIANTEXT,
  500.             "Russian annotation", "paragraph", 1);
  501.  
  502.     PDF_add_launchlink(p, 300, 300, 400, 350, "foo.txt");
  503.  
  504.     PDF_set_border_color(p, (float) 0.0, (float) 1.0, (float) 0.0);
  505.     PDF_set_border_dash(p, (float) 3.0, (float) 2.0);
  506.  
  507.     PDF_add_pdflink(p, 400, 200, 500, 250, "cell.pdf", 2, "fitpage");
  508.  
  509.     PDF_set_border_color(p, (float) 1.0, (float) 1.0, (float) 0.0);
  510.     PDF_set_border_dash(p, (float) 3.0, (float) 2.0);
  511.  
  512.     PDF_add_locallink(p, 500, 100, 550, 150, 8, "fitwidth");
  513.  
  514.     PDF_set_border_style(p, "solid", (float) 7.0);
  515.     PDF_set_border_color(p, (float) 0.0, (float) 1.0, (float) 1.0);
  516.     PDF_set_border_dash(p, (float) 0.0, (float) 0.0);
  517.  
  518.     PDF_add_weblink(p, 100, 150, 300, 250, "http://malik.piripiri.de");
  519.  
  520.     PDF_end_page(p);
  521.  
  522.     MESSAGE("done\n");
  523.  
  524. #undef NOTETEXT
  525. #undef FILENAME
  526. #undef MIMETYPE
  527. #undef RUSSIANTEXT
  528. #undef GREEKTEXT
  529. }
  530.  
  531. /* ------------------------------------------------------------- */
  532. static void
  533. centered_text(PDF *p)
  534. {
  535.     float    y, width;
  536.     char    **cp;
  537.     int        textfont, titlefont;
  538.     char    *title = "Der Zauberlehrling";
  539.     char    *subtitle ="Johann Wolfgang von Goethe";
  540. #ifndef MAC
  541.     char    *poem[] = {
  542.             "Hat der alte Hexenmeister",
  543.             "Sich doch einmal wegbegeben!",
  544.             "Und nun sollen seine Geister",
  545.             "Auch nach meinem Willen leben.",
  546.             "Seine Wort\222 und Werke",
  547.             "Merkt ich und den Brauch,",
  548.             "Und mit Geistesst\344rke",
  549.             "Tu ich Wunder auch.",
  550.             "Walle! walle",
  551.             "Manche Strecke,",
  552.             "Da\337, zum Zwecke,",
  553.             "Wasser flie\337e",
  554.             "Und mit reichem, vollem Schwalle",
  555.             "Zu dem Bade sich ergie\337e.",
  556.             NULL };
  557. #else
  558. /* We don't want 8-bit characters in the source, therefore different
  559.  * flavors of the sample text will be used for Mac and non-Mac systems.
  560.  * These only differ in the special characters (octal notation).
  561.  */
  562.     char    *poem[] = {
  563.             "Hat der alte Hexenmeister",
  564.             "Sich doch einmal wegbegeben!",
  565.             "Und nun sollen seine Geister",
  566.             "Auch nach meinem Willen leben.",
  567.             "Seine Wort\325 und Werke",
  568.             "Merkt ich und den Brauch,",
  569.             "Und mit Geistesst\212rke",
  570.             "Tu ich Wunder auch.",
  571.             "Walle! walle",
  572.             "Manche Strecke,",
  573.             "Da\247, zum Zwecke,",
  574.             "Wasser flie\247e",
  575.             "Und mit reichem, vollem Schwalle",
  576.             "Zu dem Bade sich ergie\247e.",
  577.             NULL };
  578. #endif
  579.  
  580. #define FONTSIZE    24
  581. #define CENTER        290
  582. #define TOP        750
  583.  
  584.     MESSAGE("Centered text test...");
  585.  
  586.     PDF_begin_page(p, a4_width, a4_height);
  587.     (void) PDF_add_bookmark(p, "Centered text", 0, 1);
  588.  
  589.     textfont = PDF_findfont(p, "Times-Roman", ENCODING, 1);
  590.     if (textfont == -1) {
  591.     fprintf(stderr, "Font 'Times-Roman' not found!\n");
  592.     return;
  593.     }
  594.  
  595.     y = TOP;
  596.  
  597.     titlefont = PDF_findfont(p, "Helvetica-Bold", ENCODING, 1);
  598.     if (titlefont == -1) {
  599.     fprintf(stderr, "Font 'Helvetica-Bold' not found!\n");
  600.     return;
  601.     }
  602.  
  603.     PDF_setfont(p, titlefont, (float) (1.5 * FONTSIZE));
  604.     width = PDF_stringwidth(p, title, textfont, PDF_get_fontsize(p));
  605.     PDF_show_xy(p, title, CENTER - width/2, y);
  606.     y -= 1.5 * FONTSIZE;
  607.  
  608.     PDF_setfont(p, titlefont, FONTSIZE/2);
  609.     width = PDF_stringwidth(p, subtitle, textfont, PDF_get_fontsize(p));
  610.     PDF_show_xy(p, subtitle, CENTER - width/2, y);
  611.     y -= 3 * FONTSIZE;
  612.  
  613.     PDF_setfont(p, textfont, FONTSIZE);
  614.  
  615.     for (cp = poem; *cp; cp++) {
  616.     width = PDF_stringwidth(p, *cp, textfont, PDF_get_fontsize(p));
  617.     PDF_show_xy(p, *cp, CENTER - width/2, y);
  618.     y -= 1.5 * FONTSIZE;
  619.     }
  620.  
  621.     PDF_end_page(p);
  622.  
  623.     MESSAGE("done\n");
  624.  
  625. #undef FONTSIZE
  626. #undef RIGHT
  627. #undef TOP
  628. }
  629.  
  630. /* ------------------------------------------------------------- */
  631. static void
  632. memory_image(PDF *p)
  633. {
  634.     char     *buf, *bp;
  635.     int        width, height, components;
  636.     int        bpc;
  637.     int        image;
  638.     int        i, j;
  639.     float    y, sx, sy;
  640.  
  641. #define LEFT        ((float) 50.0)
  642.  
  643.     width    = 256;
  644.     height    = 1;
  645.     bpc        = 8;
  646.     components    = 3;
  647.  
  648.     MESSAGE("Memory image test...");
  649.  
  650.     sx = (float) 3.0;        /* desired horizontal scaling factor */
  651.     sy = (float) 128.0;        /* desired height of one color band */
  652.  
  653.     buf = calloc((size_t) (width * height * components), 1);
  654.  
  655.     if (buf == NULL) {
  656.     fprintf(stderr, "Not enough memory for memory image!\n");
  657.     return;
  658.     }
  659.  
  660.     /* now fill the buffer with fake image data (simple color ramp) */
  661.     for (bp = buf, i=0; i<height; i++) {
  662.     for (j=0; j<width; j++) {
  663.         *bp++ = (char) (j % 256);    /* red blend */
  664.         *bp++ = 0;
  665.         *bp++ = 0;
  666.     }
  667.     }
  668.  
  669.     /* 
  670.      * In positioning the images below, we will have to compensate 
  671.      * for the scaling.
  672.      */
  673.     y = LEFT;
  674.  
  675.     image = PDF_open_image(p, "raw", "memory", buf, width*height*components,
  676.         width, height, components, bpc, "");
  677.     if (image == -1) {
  678.     fprintf(stderr, "Not enough memory for memory image!\n");
  679.     free(buf);
  680.     return;
  681.     }
  682.  
  683.     PDF_begin_page(p, 900, 600);
  684.     (void) PDF_add_bookmark(p, "Memory image", 0, 1);
  685.  
  686.     /* 
  687.      * Since the image interface doesn't support non-proportional
  688.      * scaling, we will use PDF_scale() instead to stretch the image.
  689.      */
  690.     PDF_scale(p, sx, sy);        /* stretch image */
  691.  
  692.     PDF_place_image(p, image, LEFT/sx, y/sy, (float) 1.0);
  693.  
  694.     for (bp = buf, i=0; i<height; i++) {
  695.     for (j=0; j<width; j++) {
  696.         *bp++ = 0;
  697.         *bp++ = (char) (j % 256);    /* green blend */
  698.         *bp++ = 0;
  699.     }
  700.     }
  701.  
  702.     y += height * sy;        /* position the image */
  703.  
  704.     image = PDF_open_image(p, "raw", "memory", buf, width*height*components,
  705.         width, height, components, bpc, "");
  706.     if (image == -1) {
  707.     fprintf(stderr, "Not enough memory for memory image!\n");
  708.     free(buf);
  709.     PDF_end_page(p);
  710.     return;
  711.     }
  712.  
  713.     PDF_place_image(p, image, LEFT/sx, y/sy, (float) 1.0);
  714.  
  715.     for (bp = buf, i=0; i<height; i++) {
  716.     for (j=0; j<width; j++) {
  717.         *bp++ = 0;
  718.         *bp++ = 0;
  719.         *bp++ = (char) (j % 256);    /* blue blend */
  720.     }
  721.     }
  722.  
  723.     y += height * sy;        /* position the image */
  724.  
  725.     image = PDF_open_image(p, "raw", "memory", buf, width*height*components,
  726.         width, height, components, bpc, "");
  727.     if (image == -1) {
  728.     fprintf(stderr, "Not enough memory for memory image!\n");
  729.     free(buf);
  730.     PDF_end_page(p);
  731.     return;
  732.     }
  733.  
  734.     PDF_place_image(p, image, LEFT/sx, y/sy, (float) 1.0);
  735.  
  736.     for (bp = buf, i=0; i<height; i++) {
  737.     for (j=0; j<width; j++) {
  738.         *bp++ = (char) (j % 256);    /* gray blend */
  739.     }
  740.     }
  741.  
  742.     y += height * sy;        /* position the image */
  743.  
  744.     components    = 1;        /* now a single component image */
  745.     image = PDF_open_image(p, "raw", "memory", buf, width*height*components,
  746.         width, height, components, bpc, "");
  747.     if (image == -1) {
  748.     fprintf(stderr, "Not enough memory for memory image!\n");
  749.     free(buf);
  750.     PDF_end_page(p);
  751.     return;
  752.     }
  753.  
  754.     PDF_place_image(p, image, LEFT/sx, y/sy, (float) 1.0);
  755.  
  756.     free(buf);
  757.     PDF_end_page(p);
  758.  
  759.     MESSAGE("done\n");
  760.  
  761. #undef LEFT
  762. }
  763.  
  764. /* ------------------------------------------------------------- */
  765. static void
  766. radial_structure(PDF *p)
  767. {
  768.     float alpha;
  769.  
  770.     MESSAGE("Radial structure test...");
  771.  
  772.     PDF_begin_page(p, a4_width, a4_height);
  773.     (void) PDF_add_bookmark(p, "Radial structure", 0, 1);
  774.  
  775.     PDF_translate(p, (float) 300.0, (float) 400.0);
  776.     PDF_setlinewidth(p, (float) 0.1);
  777.  
  778. #ifdef NOT_EXACT
  779.     /* 
  780.      * Mathematically, the following are equivalent. However, due
  781.      * to massive accumulation of rounding errors the first variant
  782.      * produces visible inaccuracy artifacts (try it!)
  783.      */
  784.     for (alpha = 0; alpha < 360; alpha++) {
  785.     PDF_moveto(p, 0.0, 0.0);
  786.     PDF_lineto(p, 250.0, 0.0);
  787.     PDF_stroke(p);
  788.     PDF_rotate(p, 1.0);
  789.     }
  790. #endif
  791.  
  792.     /* better solution: don't accumulate rounding errors */
  793.     for (alpha = 0; alpha < 360; alpha++) {
  794.     PDF_save(p);
  795.     PDF_rotate(p, alpha);
  796.     PDF_moveto(p, (float) 0.0, (float) 0.0);
  797.     PDF_lineto(p, (float) 250.0, (float) 0.0);
  798.     PDF_stroke(p);
  799.     PDF_restore(p);
  800.     }
  801.  
  802.     PDF_end_page(p);
  803.  
  804.     MESSAGE("done\n");
  805. }
  806.  
  807. /* ------------------------------------------------------------- */
  808. static void
  809. random_data_graph(PDF *p)
  810. {
  811.     float x;
  812.  
  813.     MESSAGE("Random graph test...");
  814.  
  815.     PDF_begin_page(p, a4_width, a4_height);
  816.     (void) PDF_add_bookmark(p, "Random graph", 0, 1);
  817.  
  818. #define STEP    ((float) 10.0)
  819. #define MARGIN    ((float) 50.0)
  820. #define RIGHT    ((float) 500.0)
  821. #define TOP    ((float) 800.0)
  822.     PDF_setlinewidth(p, 2);
  823.     PDF_moveto(p, RIGHT, MARGIN);
  824.     PDF_lineto(p, MARGIN, MARGIN);
  825.     PDF_lineto(p, MARGIN, TOP);
  826.     PDF_setgray_stroke(p, 0);        /* black */
  827.     PDF_stroke(p);
  828.  
  829.     PDF_setlinewidth(p, 1);
  830.     PDF_moveto(p, MARGIN, MARGIN);
  831.  
  832.     /* construct some random graph data */
  833.     PDF_setrgbcolor_stroke(p, (float) 1.0, (float) 0, (float) 0);/* red */
  834.     for (x=MARGIN; x<RIGHT; x+=STEP)
  835.     PDF_lineto(p, x, x + (TOP-MARGIN)/(float)2.0*rand()/(RAND_MAX+(float)1.0));
  836.  
  837.     PDF_stroke(p);
  838.  
  839.     PDF_setrgbcolor_stroke(p, (float) 0, (float) 1.0, (float) 0);/* green */
  840.     PDF_moveto(p, MARGIN, MARGIN);
  841.     for (x=MARGIN; x<RIGHT; x+=STEP)
  842.     PDF_lineto(p, x, 
  843.         MARGIN + TOP*(x-MARGIN)*(x-MARGIN)/((RIGHT-MARGIN)*(RIGHT-MARGIN)));
  844.  
  845.     PDF_stroke(p);
  846.  
  847.     PDF_setrgbcolor_stroke(p, (float) 0, (float) 0, (float) 1.0);/* blue */
  848.     PDF_moveto(p, MARGIN, MARGIN);
  849.     for (x=MARGIN; x<RIGHT; x+=STEP)
  850.     PDF_lineto(p, x, MARGIN + x + MARGIN*rand()/(RAND_MAX+(float)1.0));
  851.  
  852.     PDF_stroke(p);
  853.  
  854.     PDF_end_page(p);
  855.  
  856.     MESSAGE("done\n");
  857.  
  858. #undef STEP
  859. #undef MARGIN
  860. #undef RIGHT
  861. #undef TOP
  862. }
  863.  
  864. /* ------------------------------------------------------------- */
  865. static void
  866. many_pages(PDF *p)
  867. {
  868.     char buf[128];
  869.     int i, font;
  870.  
  871. #define FONTSIZE    24
  872. #define FONTNAME    "Times-Roman"
  873. #define PAGECOUNT    1000
  874.  
  875.     MESSAGE("Many pages test...");
  876.  
  877.     for (i = 1; i <= PAGECOUNT; i++) {
  878.     PDF_begin_page(p, a4_width, a4_height);
  879.  
  880.     if (i == 1)
  881.         (void) PDF_add_bookmark(p, "Many pages", 0, 1);
  882.  
  883.     font = PDF_findfont(p, FONTNAME, "default", 1);
  884.     if (font == -1) {
  885.         fprintf(stderr, "Font %s not found!\n", FONTNAME);
  886.         return;
  887.     }
  888.     PDF_setfont(p, font, FONTSIZE);
  889.  
  890.     sprintf(buf, "Page %d", i);
  891.     PDF_show_xy(p, buf, 200, 600);
  892.  
  893.     PDF_end_page(p);
  894.     }
  895.  
  896.     MESSAGE("done\n");
  897. }
  898.  
  899. static unsigned
  900. #ifdef WIN32
  901. __stdcall        /* needed for threads */
  902. #endif
  903. Do_PDFlib_tests(void *arg)
  904. {
  905.     char    filename[50];
  906.     PDF        *p;
  907.  
  908.     sprintf(filename, "pdftest%03ld.pdf", (long) arg);
  909.  
  910.     printf("Creating PDFlib test file '%s'!\n", filename);
  911.  
  912.     p = PDF_new();
  913.  
  914.     if (PDF_open_file(p, filename) == -1) {
  915.         printf("Couldn't open PDF file '%s'!\n", filename);
  916.     PDF_ENDTHREAD(1);
  917.     return 1;
  918.     }
  919.  
  920.     PDF_set_info(p, "Keywords", "image graphics text hypertext");
  921.     PDF_set_info(p, "Subject", "Check many PDFlib function calls");
  922.     PDF_set_info(p, "Title", "PDFlib test program");
  923.     PDF_set_info(p, "Creator", "PDFtest");
  924.     PDF_set_info(p, "Author", "Thomas Merz");
  925.  
  926.     gif_image(p);
  927.     jpeg_image(p);
  928. #ifdef HAVE_LIBTIFF
  929.     tiff_image(p);
  930. #endif
  931.     ccitt_image(p);
  932.     centered_text(p);
  933.     character_table(p);
  934.     annotations(p);
  935.     bookmarks(p);
  936.     grid(p);
  937.     shaded_circle(p);
  938.     memory_image(p);
  939.     radial_structure(p);
  940.     random_data_graph(p);
  941.     many_pages(p);
  942.  
  943.     PDF_close(p);
  944.     PDF_delete(p);
  945.  
  946.     printf("\nPDFlib test file '%s' finished!\n", filename);
  947.  
  948.     PDF_ENDTHREAD(0);
  949.  
  950.     return 0;
  951. }
  952.  
  953. #define PDF_MAXTHREADS 4
  954.  
  955. int
  956. main(int argc, char *argv[])
  957. {
  958. #ifdef WIN32
  959.     unsigned t, w, thread_id;
  960.  
  961.     HANDLE hThread[PDF_MAXTHREADS];
  962.  
  963.     /* do a multi-threaded test */
  964.     for (t=0; t < PDF_MAXTHREADS; t++) {
  965.     hThread[t] =(HANDLE) _beginthreadex(NULL, 0, &Do_PDFlib_tests,
  966.                     (void *)t, 0, &thread_id );
  967.     if (hThread[t] == 0) {
  968.         printf("Couldn't create thread %ud\n", t);
  969.         break;
  970.     }
  971.     }
  972.  
  973.     for (w=0; w < t; w++) {
  974.     WaitForSingleObject(hThread[w], INFINITE);
  975.     CloseHandle(hThread[w]);
  976.     }
  977. #else
  978.  
  979.     /* do a single test */
  980.     Do_PDFlib_tests((void *) 0L);
  981.  
  982. #endif
  983.  
  984.     exit(0);
  985.  
  986.     return 0;    /* shut up compiler warnings */
  987. }
  988.